import {
    AfterViewChecked,
    AfterViewInit,
    Component,
    ElementRef,
    EventEmitter,
    Input,
    OnChanges,
    OnDestroy,
    OnInit,
    Output,
    SimpleChanges,
    ViewChild
} from '@angular/core';
import {HttpService} from '@kylin/http';

import {NzMessageService} from 'ng-zorro-antd';
import {StatusSelectorComponent} from './status-selector/status-selector.component';
import {BtnInfo, BtnsGen} from './buttons/interface';
import {SelectorGen} from './selector/interface'
import {StatusSelector} from './status-selector/interface'
import {RequestInfo, TableGen} from './interface'
import {SelectorComponent} from './selector/selector.component';
import {DatePipe} from '@angular/common';
import {ActivatedRoute} from '@angular/router';

declare let window: any;
declare const $: any;

@Component({
    selector: 'kylin-list-page',
    templateUrl: './list-page.component.html',
    styleUrls: [
        './list-page.component.less'
    ]
})
export class ListPageComponent implements OnInit, OnDestroy, OnChanges, AfterViewChecked, AfterViewInit {
    @Input() statusSelector: StatusSelector;
    @Input() selectorGen: SelectorGen;
    @Input() btnsGen: BtnsGen;

    @Input() set tableGen(val: TableGen) {
        this._tableGen = val;
        this.initSortMap();
        if (val.totalProps) {
            val.totalProps.map(item => this._totalPropsMap[item] = true); // 绑定合计列
        }
    };

    _tableGen: TableGen;
    _totalPropsMap: { [key: string]: boolean } = {}; // 绑定合计列
    tableData: Array<any> = [];
    @ViewChild('selectorCmpt', {static: true}) selectorCmpt: SelectorComponent;
    @ViewChild('statusSelectorCmpt', {static: true}) statusSelectorCmpt: StatusSelectorComponent;
    // region: for AFBM(青海草饲)
    colorMap = {
        '待市级审核': '#CC66FF',
        '待省级审核': '#6666FF',
        '已完成': '#FF0000',
        '待提交': '#00CC00',
        '已关闭': '#868686',
        '待省级下达': '#FF0099'
    };
    // endregion

    // ---------------- 查询功能属性定义开始 -----------------
    @Input() queryReqInfo: RequestInfo; // 查询操作，request的相关参数
    @Input() nzTableSize = 'middle';
    allChecked = false;
    indeterminate = false;
    // 当前选中的条目，以及选中状态
    @Output() statusEmit = new EventEmitter<{ allChecked: boolean, indeterminate: boolean, list: Array<any> }>();
    selectedList: Array<any>; // 表格中选中的数据集合
    pageIndex = 1;
    @Input() pageSize = 10;
    total: number;
    totalPage = 0;
    editedObj: any;
    currentEditIpt: ElementRef;
    editableCellWidth: string; // 为避免文本切换到输入框时，输入框过大导致表格变形，将原宽度保留
    statistics = false; // 页数与数据的统计信息
    curSortInfo: any;
    sortMap: any = {};

    @ViewChild('currentEdit', {static: true}) set editEleRef(content: ElementRef) {
        if (content && content.nativeElement) {
            this.currentEditIpt = content;
        }
    };

    @Output() onPageRefresh = new EventEmitter<any>();
    @Output() queryResultEmit = new EventEmitter<any>();
    allDisabled = false; // 是否所有checkbox都不可点击
    currentEditHex: {
        ele: any;
        data: any;
        prop: any;
    };

    // ---------------- 表格生成属性定义结束 -----------------
    @Input() loading: boolean;
    winodwHex = window; // TODO 当页面出现滚动时,table优先滚动
    funSet: any; // 对外提供函数条用接口集合

    constructor(private http: HttpService, private message: NzMessageService, private datePipe: DatePipe, private router: ActivatedRoute) {
    }

    ngOnInit() {
        this.initFunSet();
        this.processTableGen();
        if (!this.selectorGen) {
            // 如无需筛选条件组件，则直接获取数去；否则待筛选组件加载完毕，根据筛选条件查询数据
            this.execQuery(); // 初始化表格数据
        }
        this.router.queryParams.subscribe(params => {
            if (params['afbmStatus'] && this.statusSelector) {
                const selectIdx = this.statusSelector.list.findIndex(item => item.key === params['afbmStatus']);
                if (selectIdx !== -1) {
                    this.statusSelector.index = selectIdx;
                }
            }
        });
        window.addEventListener('click', this.finishEdit);
    }

    ngOnChanges(changes: SimpleChanges) {
        if (changes.tableGen && !changes.tableGen.firstChange) {
            this.execQuery();
        }
    }

    ngAfterViewInit() {
        this.initFunSet(); // 初始化函数集
    }

    ngAfterViewChecked() {
        if (this.statistics) {
            if ($('.pagination-info').length) {
                $('.pagination-info').remove();
            }
            if (this.tableData.length > 0) {
                $('.ant-pagination').prepend(`<span class="pagination-info" style="vertical-align: middle;">共<span style="color:#f00">${this.totalPage}</span>页/共<span style="color:#f00">${this.total}</span> 条数据</span>`);
                this.statistics = false;
            }
        }
    }

    initFunSet() {
        this.funSet = {
            refreshList: this.refreshList,
            getSelected: this.selectorCmpt ? this.selectorCmpt.getSelectedMap : Function.prototype,
            sentQueryReq: this.getDataByQueryReqInfo,
            getCurrentStatus: this.statusSelectorCmpt ? this.statusSelectorCmpt.getCurrentStatus : Function.prototype,
            getTotalByStatus: this.statusSelectorCmpt ? this.statusSelectorCmpt.getTotalByStatus : Function.prototype,
            sendRequest: this.sendRequest,
            getCurSortInfo: this.getCurSortInfo,
            getPagination: () => {
                return {
                    total: this.total,
                    size: this.pageSize,
                    current: this.pageIndex
                };
            }
        };
    }

    selectedIdxChange(params) {
        this.execQuery(params.status || {});
    }

    getQueryParams() {
        return {
            ...this.funSet.getSelected(),
            ...this.funSet.getCurrentStatus(),
            ...this.getCurSortInfo()
        }
    }

    execQuery(params?: any) {
        this.getDataByQueryReqInfo({...(this.getQueryParams()), ...params});
    }

    getDataByQueryReqInfo = (params?: any) => {
        const queryInfo = {...this.queryReqInfo};
        const reqParams = {
            current: this.pageIndex,
            size: this.pageSize,
            ...params,
            ...queryInfo.params
        };
        return new Promise((resolve, reject) => {
            this.sendRequest(queryInfo, reqParams).then(rep => {
                this.loading = false;
                if (rep.status === 200) {
                    this.onPageRefresh.emit({...(this.funSet)});
                    if (!rep.result) {
                        rep.result = {
                            records: [],
                            current: 1,
                            size: 10,
                            total: 0
                        };
                    }
                    if (!rep.result.records.length && rep.result.current > 1) {
                        // 当前页没有数据且不为第一页，那么自动往前一页查询
                        this.getDataByQueryReqInfo({params, current: params.current - 1});
                        return;
                    }
                    this.loading = false;
                    this.pageIndex = rep.result.current;
                    if (rep.result.size !== this.pageSize) {
                        this.pageSize = rep.result.size;
                    }
                    this.total = rep.result.total;
                    this.tableData = this.processTableData(rep.result.records);
                    this.totalPage = Math.ceil(this.total / this.pageSize);
                    this.statistics = true;
                    this.refreshStatus();
                    this.funSet.getTotalByStatus();
                    this.queryResultEmit.emit({tableData: this.tableData, reqParams});
                } else {
                    this.message.error(`请求数据失败,${rep.message}`);
                }
                resolve({tableData: this.tableData, reqParams});
            }).catch(error => {
                this.loading = false;
                this.tableData = [];
                this.selectedList = [];
                this.queryResultEmit.emit({tableData: [], reqParams: {}});
                this.message.error('请求数据失败');
                reject(error);
            });
        });
    }

    processTableData(list: Array<any>) {
        let processedList = this._tableGen.dataProcess ? this._tableGen.dataProcess(list, this.funSet) : list;
        if (this._tableGen) {
            processedList = processedList.map((listItem, index) => {
                if (!this._tableGen.noChecked) {
                    // 如果表格具备勾选能力，则在每条数据中加入tableChecked属性
                    listItem.tableChecked = false;
                }
                if (this._tableGen.serialNumber) {
                    listItem.tableSerialNumber = (this.pageIndex - 1) * this.pageSize + index + 1;
                }
                if (this._tableGen.disabledCheckbox) {
                    listItem.disabledCheckbox = this._tableGen.disabledCheckbox(listItem);
                }
                return listItem;
            });
        }
        return processedList;
    }

    handleBtnsClick(btnInfo: BtnInfo) {
        btnInfo.klClick(this.selectedList, this.funSet);
    }

    // ---------------- 表格相关函数部分开始 -----------------
    change(rst) {
        if (rst.status === false) {
            rst.status = true;
        } else {
            rst.status = false;
        }
    }

    processTableGen() {
        /** 如特殊项目需对表格生成元素做特殊处理，可在此函数处理 **/
    }

    checkAll(value: boolean): void {
        this.tableData.forEach(data => {
            if (!data.disabledCheckbox) {
                // 全选操作跳过disabled的数据行
                data.tableChecked = value;
            }
        });
        this.refreshStatus();
    }

    refreshStatus(): void {
        let disableLen = 0;
        let allChecked = this.tableData.every(value => {
            if (value.disabledCheckbox) {
                disableLen++
            }
            return value.tableChecked === true || value.disabledCheckbox === true
        }) && this.tableData.length > 0;
        allChecked = this.tableData.length > disableLen ? allChecked : false;
        const allUnChecked = this.tableData.every(value => !value.tableChecked || value.disabledCheckbox === true);
        const allDisabled = this.tableData.every(value => value.disabledCheckbox === true);
        this.allChecked = allChecked;
        this.indeterminate = (!allChecked) && (!allUnChecked);
        this.allDisabled = allDisabled;
        this.emitCheckedStatus();
    }

    emitCheckedStatus() {
        const checkedList = new Array<any>();
        this.tableData.map(item => {
            if (item.tableChecked) {
                checkedList.push(item);
            }
        });
        this.selectedList = checkedList;
        this.statusEmit.emit(
            {
                allChecked: this.allChecked,
                indeterminate: this.indeterminate,
                list: checkedList
            }
        );
    }

    onPageIndexChange(current) {
        this.execQuery({current});
    }

    onPageSizeChange(size) {
        this.execQuery({size});
    }

    refreshList = () => {
        this.execQuery();
        if (this.statusSelectorCmpt) {
            this.statusSelectorCmpt.getTotalByStatus();
        }
    }


    startEdit(data: any, prop: string, e) {
        e.stopPropagation();
        if (this.editedObj) {
            this.finishEdit(e); // 事件冒泡被阻止，因此需关闭之前的编辑单元格
        }
        this.editableCellWidth = e.currentTarget.clientWidth + 'px';
        this.editedObj = {data, prop};
        this.editedObj.data.editStatus[prop] = true;
    }

    finishEdit = (e) => {
        if (this.editedObj) {
            if (!this.currentEditIpt.nativeElement.contains(e.target)) {
                this.editedObj.data.editStatus[this.editedObj.prop] = false;
            }
            if (e.type === 'keyup' && e.code === 'Enter') {
                this.editedObj.data.editStatus[this.editedObj.prop] = false;
            }
        }
    }

    parseImgPath(pathStrArr) {
        let source: string;
        if (pathStrArr.startsWith('[')) {
            source = pathStrArr;
        } else {
            source = `[${pathStrArr}]`;
        }
        return JSON.parse(source);
    }

    sendRequest = (reqInfo: RequestInfo, reqParams): Promise<any> => {
        this.loading = true;
        if (this._tableGen.localData) {
            return new Promise<any>(rsl => rsl({
                code: 'OK',
                message: 'OK',
                result: {
                    'current': 1,
                    'pages': 1,
                    'records': this._tableGen.localData,
                    'size': 10,
                    'total': 20
                },
                status: 200
            }));
        } else {
            return this.http[(reqInfo.method || 'get').toLowerCase()](reqInfo.path, reqParams);
        }
    }

    ngOnDestroy() {
        window.removeEventListener('click', this.finishEdit);
    }

    getFormatDate(timestamp, format: string) {
        return timestamp ? this.datePipe.transform(timestamp, format || 'yyyy/MM/dd HH:mm:ss') : '';
    }

    toggleEditStatus(event, data, editingProp) {
        event.stopPropagation();
        console.log('双击事件')
        // 加 10px: nzInput拥有更大宽度的边框和padding等等，加10px让 span的内容完整显示在nzInput中
        this.editableCellWidth = event.target.clientWidth + 10 + 'px';
        if (this.currentEditHex && this.currentEditHex['data']['prop']) {
            this.currentEditHex['data']['prop'] = false;
        }
        data[editingProp] = true;
        this.currentEditHex = {
            ele: event.target,
            data: data,
            prop: editingProp
        };
    }

    registerClose(editingInput, data, editingProp) {
        const toggleEditStatus = (e) => {
            console.log('单击事件')
            // TODO 结构对比，删除之前代码
            event.stopPropagation();
            if (e.target !== editingInput) {
                data[editingProp] = false;
                this.currentEditHex = void 0;
            }
            window.removeEventListener('click', toggleEditStatus);
        };
        window.addEventListener('click', toggleEditStatus);
        return 0;
    }

    getSumByProp(prop: string) {
        let sum = 0;
        this.tableData.map(item => sum += +item[prop]);
        return sum;
    }

    handleSort(params) {
        this.curSortInfo = {
            order: params.value ? params.value.replace('end', '') : '',
            orderBy: params.key,
        };
        for (const prop in this.sortMap) {
            this.sortMap[prop] = (prop === params.key ? params.value : null);
        }
        this.execQuery({
            current: 1,
            size: 10
        });
    }

    initSortMap() {
        this._tableGen.cols.map(col => {
            if (col.sort || col.sort === '') {
                this.sortMap[col.sort || col.prop] = null;
            }
        });
    }

    getCurSortInfo = () => {
        if (this.curSortInfo && this.curSortInfo.order && this.curSortInfo.orderBy) {
            return this.curSortInfo;
        } else {
            return;
        }
    }
}
